package client

import (
	"errors"
	"fmt"
	_type "gitee.com/freedom_feel/gui-bos-api/common/type"
	"io"
	"os"
	"strings"

	util "gitee.com/freedom_feel/gui-bos-api/common/utils"
	"gitee.com/freedom_feel/gui-bos-api/global"
	"gitee.com/freedom_feel/gui-bos-api/logs"
	"gitee.com/freedom_feel/gui-bos-api/models"
	"github.com/bytedance/sonic"

	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"gorm.io/gorm/schema"
)

var db *gorm.DB

func InitMysql() {
	//主要是mysql 字段 读取 后续可以再添加
	mysqlCfg := global.Config.Mysql
	{
		// 连接字符串，需要替换成您的数据库信息
		//dsn := fmt.Sprintf("root:%v@tcp(%v:%v)/", pwd, hot, port)
		//Db, errs := gorm.Open(mysql.Open(dsn), &gorm.Config{})
		//if errs != nil {
		//	logs.Info(fmt.Sprintf("数据库连接失败:%v", errs))
		//	return nil, errors.New("本地数据库连接失败")
		//}
		//logs.Info("数据库连接成功,创建数据库...")
		// 自动创建数据库
		//sql := fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %v DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci", bdStr)
		//result := Db.Exec(sql)
		//if result.Error != nil {
		//	logs.Info(fmt.Sprintf("数据库创建失败:%v", errs))
		//}
		//logs.Info("数据库创建成功")
		//"root:123456@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"
	}
	dsn := fmt.Sprintf("root:%v@tcp(%v:%v)/%v?charset=utf8mb4&parseTime=True&loc=Local", mysqlCfg.MysqlPwd, mysqlCfg.MysqlHot, mysqlCfg.MysqlPort, mysqlCfg.Database)
	//	return nil, errors.New("本地数据库创建失败")
	var err error
	db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: logger.Default.LogMode(logger.Info),
		NamingStrategy: schema.NamingStrategy{
			SingularTable: true, // 使用单数表名，启用该选项，此时，`User` 的表名应该是 `user`
		},
	})
	// db.Debug()
	if err != nil {
		logs.Error(err.Error())
		_type.ErrChan <- *_type.ErrSystem("mysql数据库连接失败")
		return
	}

	initAutoMg(db)
	// 使用logger记录一条日志
	logs.Info("initialize a Mysql database success")
	//AutoCreateTable("area.sql", DB)
	//logs.Info("地区 area 数据添加,可以执行任务")
	return
}

func initAutoMg(DB *gorm.DB) {
	err := DB.AutoMigrate(
		&models.Boss{},
		&models.Area{},
		&models.Task{},
		&models.TaskKey{},
		&models.User{},
		&models.PhotoHistory{},
		&models.Role{},
		&models.Product{},
		&models.ProductCategory{},
		&models.HotProduct{})
	if err != nil {
		panic("auto migrate failed" + err.Error())
	}
	return
}

func AutoCreateTable(name string, db *gorm.DB) {
	sqlFile, err := os.Open(name)
	if err != nil {
		logs.Info("failed to open sql file")
	}
	defer sqlFile.Close()

	// 读取 SQL 文件内容
	sqlBytes, err := io.ReadAll(sqlFile)
	if err != nil {
		logs.Info("failed to read sql file")
	}

	// 执行 SQL 文件中的语句
	sqlArr := strings.Split(string(sqlBytes), ";")
	for _, sql := range sqlArr {
		sql = strings.TrimSpace(sql)
		if sql == "" {
			continue
		}
		errs := db.Exec(sql).Error
		if errs != nil {
			logs.Info("数据库导入失败:" + errs.Error())
			return
		}
	}
}

func FindAll() (boosdata []models.SelectBoss, err error) {
	res := db.Find(&boosdata)
	if res.Error != nil {
		fmt.Println(res.Error)
		err = errors.New("获取数据错误")
		return nil, err
	}
	return boosdata, nil
}

func Del(name string) bool {
	res := db.Where("job_name= ?", name).Delete(&models.Boss{})
	if res.Error != nil {
		fmt.Println(res.Error)
		return false
	}
	return true
}

func FindAreaData(address string) (boosdata []models.SelectBoss, err error) {
	res := db.Where("city_name=? AND deleted_at IS NULL", address).Find(&boosdata)
	if res.Error != nil {
		logs.Info(res.Error.Error())
		return nil, errors.New("获取数据错误")
	}

	return boosdata, nil
}

func Insert(cityName, cityCode string) error {
	ad := models.Area{
		CityName: cityName,
		CityCode: cityCode,
	}
	res := db.Create(&ad)
	if res.Error != nil {
		fmt.Println(res.Error)
		return errors.New("添加错误")
	}
	return nil
}

func FindOneAreaCode(cityName string) (area models.Area, err error) {
	res := db.Where("city_name=? AND deleted_at IS NULL", cityName).First(&area)
	if res.Error != nil {
		fmt.Println(res.Error)
		return area, errors.New("查询错误或该系统内不存在此地区")
	}
	if area.CityCode == "" {
		return area, errors.New("未找到该地区活不存在")
	}
	return area, err
}

func Query(key string) (tk models.Task, err error) {
	res := db.Where("task_key =?", key).Find(&tk)
	if res.Error != nil {
		fmt.Println(res.Error)
		return tk, errors.New("获取数据错误")
	}
	return tk, nil
}

func QueryPtd(id string) (ptd models.Product, err error) {
	res := db.Where("id =?", id).Find(&ptd)
	if res.Error != nil {
		fmt.Println(res.Error)
		return ptd, errors.New("获取数据错误")
	}
	return ptd, nil
}

func CreatTk(task *models.Task) error {
	res := db.Transaction(func(tx *gorm.DB) error {
		tx.Debug()
		return tx.Create(task).Error
	})
	if res != nil {
		fmt.Println(res.Error())
		return errors.New("任务创建失败")
	}
	return nil
}

func UpdateTk(taskKey, status string, data interface{}) error {
	marshal, _ := sonic.Marshal(data)
	res := db.Transaction(func(tx *gorm.DB) error {
		tx.Debug()
		return tx.Where("task_key= ? ", taskKey).Updates(models.Task{TaskStatus: status, TaskData: marshal}).Error
	})
	if res != nil {
		fmt.Println(res.Error())
		return errors.New("任务更新失败")
	}
	return nil
}

func UpdateUserPhoto(uid, imgSrc string) error {
	res := db.Transaction(func(tx *gorm.DB) error {
		tx.Debug()
		return tx.Table("user").Where("user_id= ? ", uid).Update("user_avatar", imgSrc).Error
	})
	if res != nil {
		return errors.New("头像更新失败")
	}
	return nil
}

func SaveHistory(photoHistory models.PhotoHistory) error {
	res := db.Transaction(func(tx *gorm.DB) error {
		tx.Debug()
		return tx.Table("photo_history").Save(&photoHistory).Error
	})
	if res != nil {
		return errors.New("头像更新失败")
	}
	return nil
}

func GetHistory(uid string) (history []models.PhotoHistory, err error) {
	res := db.Where("user_id = ? and is_new = 1", uid).Find(&history)
	if res.Error != nil {
		logs.Error(fmt.Sprintf("获取历史记录失败: %v", res.Error))
		return nil, fmt.Errorf("获取历史记录失败")
	}
	return history, nil
}

func UpdateHistory(uid string) error {
	res := db.Transaction(func(tx *gorm.DB) error {
		tx.Debug()
		return tx.Table("photo_history").Where("user_id= ?", uid).Update("is_new", "0").Error
	})
	if res != nil {
		return errors.New("头像更新失败")
	}
	return nil
}

func QueryTk(taskKey string) (task models.TaskKey, err error) {
	res := db.Where("task_key=?", taskKey).Find(&task)
	if res.Error != nil {
		fmt.Println(res.Error)
		return models.TaskKey{}, errors.New("获取任务key失败")
	}
	return task, nil
}

func UserLoginByMobile(mobile string) (u models.User, err error) {
	if strings.Contains(mobile, "@") {
		res := db.Where("email = ?", mobile).First(&u)
		if res.Error != nil {
			fmt.Println(res.Error)
			return models.User{}, errors.New("邮箱不存在，请先注册！！！")
		}
	} else {
		res := db.Where("mobile = ?", mobile).First(&u)
		if res.Error != nil {
			fmt.Println(res.Error)
			return models.User{}, errors.New("该手机不存在，请先注册！！！")
		}
	}
	return u, nil
}

func QueryUser(username, mobile string) (u models.User, err error) {
	if strings.Contains(mobile, "@") {
		res := db.Where("email = ? and username = ?", mobile, username).First(&u)
		if res.Error != nil {
			fmt.Println(res.Error)
			return models.User{}, errors.New("邮箱不存在，请先注册！！！")
		}
	} else {
		res := db.Where("mobile = ? and username = ?", mobile, username).First(&u)
		if res.Error != nil {
			fmt.Println(res.Error)
			return models.User{}, errors.New("该手机不存在，请先注册！！！")
		}
	}
	return u, nil
}

func QueryUser1(mobile string) (u models.User, err error) {
	if strings.Contains(mobile, "@") {
		res := db.Where("email = ? ", mobile).First(&u)
		if res.Error != nil {
			fmt.Println(res.Error)
			return models.User{}, errors.New("邮箱不存在，请先注册！！！")
		}
	} else {
		res := db.Where("mobile = ? ", mobile).First(&u)
		if res.Error != nil {
			fmt.Println(res.Error)
			return models.User{}, errors.New("该手机不存在，请先注册！！！")
		}
	}
	return u, nil
}

func UpdatePwd(username, mobile, pwd string) error {
	res := db.Transaction(func(tx *gorm.DB) error {
		tx.Debug()
		if strings.Contains(mobile, "@") {
			return tx.Table("user").Where("email = ?", mobile).Update("password", pwd).Error
		} else {
			return tx.Table("user").Where("mobile = ?", mobile).Update("password", pwd).Error
		}
	})
	if res != nil {
		return errors.New("密码更新失败")
	}
	return nil
}

func UpdatePwd1(mobile, pwd string) error {
	res := db.Transaction(func(tx *gorm.DB) error {
		tx.Debug()
		if strings.Contains(mobile, "@") {
			return tx.Table("user").Where("email = ?", mobile).Update("password", pwd).Error
		} else {
			return tx.Table("user").Where("mobile = ?", mobile).Update("password", pwd).Error
		}
	})
	if res != nil {
		return errors.New("密码更新失败")
	}
	return nil
}

func GetUserInfoByUid(uid string) (models.User, error) {
	var u models.User
	res := db.Where("user_id = ?", uid).First(&u)
	if res.Error != nil {
		logs.Error(res.Error.Error())
		return models.User{}, errors.New("用户名不存在，请先注册！！！")
	}
	return u, nil
}

func UserLoginByUsername(username, password string) (models.User, error) {
	var u models.User
	res := db.Where("username = ?", username).First(&u)
	if res.Error != nil {
		fmt.Println(res.Error)
		return models.User{}, errors.New("用户名不存在,请先注册")
	}
	if !util.VerifyPasswordNew(password, u.Password, global.PwdKeyNew) {
		return models.User{}, errors.New("账号或密码错误")
	}
	return u, nil
}

func UserInsert(mobile string, u *models.User) error {
	var us models.User
	res := db.Where("mobile=?", mobile).First(&us)
	if res.Error == nil || res.Row() != nil {
		return errors.New("该手机号已注册,请核查")
	}
	err := db.Transaction(func(tx *gorm.DB) error {
		tx.Debug()
		return tx.Table("user").Create(u).Error
	})
	if err != nil {
		logs.Error(err.Error())
		return errors.New("用户注册失败,请稍后重试")
	}
	return nil

}

func GetUserAll() (data []models.User, err error) {
	res := db.Find(&data)
	if res.Error != nil {
		logs.Error(res.Error)
		return nil, _type.ErrMsg("获取数据错误")
	}
	return data, nil

}

func UpdateDC(uid string, days string) (err error) {
	res := db.Transaction(func(tx *gorm.DB) error {
		tx.Debug()
		return tx.Table("user").Where("user_id= ? ", uid).Update("days_count", days).Error
	})
	if res != nil {
		logs.Error(res.Error())
		return errors.New("任务更新失败")
	}
	return nil

}

func Transaction(taskName, key string) error {
	// 将任务信息存入数据库
	errTK := db.Transaction(func(tx *gorm.DB) error {
		return tx.Create(&models.TaskKey{
			TaskName:  taskName,
			TaskKey:   key,
			NotifyUrl: global.NotifyUrl,
		}).Error
	})
	if errTK != nil {
		logs.Error("Transaction failed: " + errTK.Error())
		return _type.ErrOther("数据存入错误")
	}
	return nil
}

func TransInsert(boos any) error {
	ok := false //类型断言一下
	if boos, ok = boos.(models.Boss); ok {
		boos = boos.(models.Boss)
	} else if boos, ok = boos.(models.Task); ok {
		boos = boos.(models.Task)
	} else {
		return _type.ErrSystem("出现未知类型")
	}
	err := db.Transaction(func(tx *gorm.DB) error {
		tx.Debug()
		// 在事务中执行一些 db 操作（从这里开始，您应该使用 'tx' 而不是 'db'）
		if err := tx.Create(&boos).Error; err != nil {
			// 返回任何错误都会回滚事务
			return err
		}
		//if err := tx.Create(&Animal{Name: "Lion"}).Error; err != nil {
		//	return err
		//}
		// 返回 nil 提交事务
		return nil
	})
	//result := db.Create(&boos)
	if err != nil {
		logs.Info(fmt.Sprintf("插入数据失败:%v", err.Error()))
		return _type.ErrSystem("数据插入事务失败")
	}
	return nil
}

func CaveRole(link string, r *models.Role) error {
	if res := db.Where("user_id =?", link); res.Error != nil || res.Row() == nil {
		return errors.New("该用户不存在,请核查")
	}
	err := db.Transaction(func(tx *gorm.DB) error {
		tx.Debug()
		return tx.Table("role").Create(r).Error
	})
	if err != nil {
		logs.Error(err.Error())
		return errors.New("管理员添加失败,请稍后重试")
	}
	return nil
}

func IsAdmin(uid uint) bool {
	var role models.Role
	res := db.Model(models.Role{}).Where("users = ?", uid).First(&role)
	if res.Error != nil {
		if strings.Contains(res.Error.Error(), "record not found") && role.Name == "" {
			return false
		}
	}
	return true
}

func FindAllProduct() (Product []models.Product, err error) {
	res := db.Find(&Product)
	if res.Error != nil {
		fmt.Println(res.Error)
		err = errors.New("获取数据错误")
		return nil, err
	}
	return Product, nil
}

func FindAllProductCategory() (ProductCategory []models.ProductCategory, err error) {
	res := db.Find(&ProductCategory)
	if res.Error != nil {
		fmt.Println(res.Error)
		err = errors.New("获取数据错误")
		return nil, err
	}
	return ProductCategory, nil
}

func FindAllHotProduct() (HotProduct []models.HotProduct, err error) {
	res := db.Find(&HotProduct)
	if res.Error != nil {
		fmt.Println(res.Error)
		err = errors.New("获取数据错误")
		return nil, err
	}
	return HotProduct, nil
}
